--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
sbapp/kivymd/uix/carousel.py 2dcc759c88f3f2471ffcf6146721200a16aadede (2dcc759c) Text, 7.04 KB
T8b949e"""
Components/Carousel
===================
:class:`~kivy.uix.boxlayout.Carousel` class equivalent. Simplifies working
with some widget properties. For example:
Carousel
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
.. code-block:: python
kv='''
YourCarousel:
BoxLayout:
[...]
BoxLayout:
[...]
BoxLayout:
[...]
'''
builder.load_string(kv)
class YourCarousel(Carousel):
def __init__(self,*kwargs):
self.register_event_type("on_slide_progress")
self.register_event_type("on_slide_complete")
def on_touch_down(self, *args):
["Code to detect when the slide changes"]
def on_touch_up(self, *args):
["Code to detect when the slide changes"]
def Calculate_slide_pos(self, *args):
["Code to calculate the current position of the slide"]
def do_custom_animation(self, *args):
["Code to recreate an animation"]
MDCarousel
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
.. code-block:: kv
MDCarousel:
on_slide_progress:
do_something()
on_slide_complete:
do_something()
"""
T8b949e# TODO: Add documentation.
Tff7b72from T7ee787kivyT7ee787.T7ee787animation Tff7b72import Te6edf3Animation
Tff7b72from T7ee787kivyT7ee787.T7ee787uixT7ee787.T7ee787carousel Tff7b72import Te6edf3Carousel
Tff7b72from T7ee787kivymdT7ee787.T7ee787theming Tff7b72import Te6edf3ThemableBehavior
Tff7b72from T7ee787kivymdT7ee787.T7ee787uixT7ee787.T7ee787behaviors Tff7b72import Te6edf3DeclarativeBehavior
Tff7b72class T56d364MDCarouselTb4b4b4(Te6edf3DeclarativeBehaviorTb4b4b4, Te6edf3ThemableBehaviorTb4b4b4, Te6edf3CarouselTb4b4b4)Tb4b4b4:
T8b949e"""
based on kivy's carousel.
.. seealso::
`kivy.uix.carousel.Carousel <https://kivy.org/doc/stable/api-kivy.uix.carousel.html>`_
"""
Te6edf3_scrolling Tff7b72= Tff7b72False
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Tff7b72*Te6edf3argsTb4b4b4, Tff7b72*Tff7b72*Te6edf3kwargsTb4b4b4)Tb4b4b4:
Tffa657superTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ff__init__Tb4b4b4(Tff7b72*Te6edf3argsTb4b4b4, Tff7b72*Tff7b72*Te6edf3kwargsTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffregister_event_typeTb4b4b4(Ta5d6ff"Ta5d6ffon_slide_progressTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffregister_event_typeTb4b4b4(Ta5d6ff"Ta5d6ffon_slide_completeTa5d6ff"Tb4b4b4)
Tff7b72def Td2a8ffon_slide_progressTb4b4b4(Tff7b72selfTb4b4b4, Tff7b72*Te6edf3argsTb4b4b4)Tb4b4b4:
T8b949e"""
Event launched when the Slide animation is progress.
remember to bind and unbid to this method.
"""
Tff7b72def Td2a8ffon_slide_completeTb4b4b4(Tff7b72selfTb4b4b4, Tff7b72*Te6edf3argsTb4b4b4)Tb4b4b4:
T8b949e"""
Event launched when the Slide animation is complete.
remember to bind and unbid to this method.
"""
Tff7b72def Td2a8ff_position_visible_slidesTb4b4b4(Tff7b72selfTb4b4b4, Tff7b72*Te6edf3argsTb4b4b4)Tb4b4b4:
Te6edf3slidesTb4b4b4, Te6edf3index Tff7b72= Tff7b72selfTff7b72.Td2a8ffslidesTb4b4b4, Tff7b72selfTff7b72.Td2a8ffindex
Te6edf3no_of_slides Tff7b72= Tffa657lenTb4b4b4(Te6edf3slidesTb4b4b4) Tff7b72- T79c0ff1
Tff7b72if Tff7b72not Te6edf3slidesTb4b4b4:
Tff7b72return
Te6edf3xTb4b4b4, Te6edf3yTb4b4b4, Te6edf3widthTb4b4b4, Te6edf3height Tff7b72= Tff7b72selfTff7b72.Td2a8ffxTb4b4b4, Tff7b72selfTff7b72.Td2a8ffyTb4b4b4, Tff7b72selfTff7b72.Td2a8ffwidthTb4b4b4, Tff7b72selfTff7b72.Td2a8ffheight
Te6edf3_offsetTb4b4b4, Te6edf3direction Tff7b72= Tff7b72selfTff7b72.Td2a8ff_offsetTb4b4b4, Tff7b72selfTff7b72.Td2a8ffdirection
Te6edf3_prevTb4b4b4, Te6edf3_nextTb4b4b4, Te6edf3_current Tff7b72= Tff7b72selfTff7b72.Td2a8ff_prevTb4b4b4, Tff7b72selfTff7b72.Td2a8ff_nextTb4b4b4, Tff7b72selfTff7b72.Td2a8ff_current
Te6edf3get_slide_container Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_slide_container
Te6edf3last_slide Tff7b72= Te6edf3get_slide_containerTb4b4b4(Te6edf3slidesTb4b4b4[Tff7b72-T79c0ff1Tb4b4b4]Tb4b4b4)
Te6edf3first_slide Tff7b72= Te6edf3get_slide_containerTb4b4b4(Te6edf3slidesTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)
Te6edf3skip_next Tff7b72= Tff7b72False
Te6edf3_loop Tff7b72= Tff7b72selfTff7b72.Td2a8ffloop
Tff7b72if Te6edf3directionTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72in Tb4b4b4[Ta5d6ff"Ta5d6ffrTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fflTa5d6ff"Tb4b4b4]Tb4b4b4:
Te6edf3xoff Tff7b72= Te6edf3x Tff7b72+ Te6edf3_offset
Te6edf3x_prev Tff7b72= Tb4b4b4{Ta5d6ff"Ta5d6fflTa5d6ff"Tb4b4b4: Te6edf3xoff Tff7b72+ Te6edf3widthTb4b4b4, Ta5d6ff"Ta5d6ffrTa5d6ff"Tb4b4b4: Te6edf3xoff Tff7b72- Te6edf3widthTb4b4b4}
Te6edf3x_next Tff7b72= Tb4b4b4{Ta5d6ff"Ta5d6fflTa5d6ff"Tb4b4b4: Te6edf3xoff Tff7b72- Te6edf3widthTb4b4b4, Ta5d6ff"Ta5d6ffrTa5d6ff"Tb4b4b4: Te6edf3xoff Tff7b72+ Te6edf3widthTb4b4b4}
Tff7b72if Te6edf3_prevTb4b4b4:
Te6edf3_prevTff7b72.Td2a8ffpos Tff7b72= Tb4b4b4(Te6edf3x_prevTb4b4b4[Te6edf3directionTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4]Tb4b4b4, Te6edf3yTb4b4b4)
Tff7b72elif Te6edf3_loop Tff7b72and Te6edf3_next Tff7b72and Te6edf3index Tff7b72== T79c0ff0Tb4b4b4:
Tff7b72if Tb4b4b4(Te6edf3_offset Tff7b72> T79c0ff0 Tff7b72and Te6edf3directionTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6ffrTa5d6ff"Tb4b4b4) Tff7b72or Tb4b4b4(
Te6edf3_offset Tff7b72< T79c0ff0 Tff7b72and Te6edf3directionTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6fflTa5d6ff"
Tb4b4b4)Tb4b4b4:
Te6edf3last_slideTff7b72.Td2a8ffpos Tff7b72= Tb4b4b4(Te6edf3x_prevTb4b4b4[Te6edf3directionTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4]Tb4b4b4, Te6edf3yTb4b4b4)
Te6edf3skip_next Tff7b72= Tff7b72True
Tff7b72if Te6edf3_currentTb4b4b4:
Te6edf3_currentTff7b72.Td2a8ffpos Tff7b72= Tb4b4b4(Te6edf3xoffTb4b4b4, Te6edf3yTb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_scrollingTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffdispatchTb4b4b4(Ta5d6ff"Ta5d6ffon_slide_progressTa5d6ff"Tb4b4b4, Te6edf3xoffTb4b4b4)
Tff7b72if Te6edf3skip_nextTb4b4b4:
Tff7b72return
Tff7b72if Te6edf3_nextTb4b4b4:
Te6edf3_nextTff7b72.Td2a8ffpos Tff7b72= Tb4b4b4(Te6edf3x_nextTb4b4b4[Te6edf3directionTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4]Tb4b4b4, Te6edf3yTb4b4b4)
Tff7b72elif Te6edf3_loop Tff7b72and Te6edf3_prev Tff7b72and Te6edf3index Tff7b72== Te6edf3no_of_slidesTb4b4b4:
Tff7b72if Tb4b4b4(Te6edf3_offset Tff7b72< T79c0ff0 Tff7b72and Te6edf3directionTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6ffrTa5d6ff"Tb4b4b4) Tff7b72or Tb4b4b4(
Te6edf3_offset Tff7b72> T79c0ff0 Tff7b72and Te6edf3directionTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6fflTa5d6ff"
Tb4b4b4)Tb4b4b4:
Te6edf3first_slideTff7b72.Td2a8ffpos Tff7b72= Tb4b4b4(Te6edf3x_nextTb4b4b4[Te6edf3directionTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4]Tb4b4b4, Te6edf3yTb4b4b4)
Tff7b72if Te6edf3directionTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72in Tb4b4b4[Ta5d6ff"Ta5d6fftTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffbTa5d6ff"Tb4b4b4]Tb4b4b4:
Te6edf3yoff Tff7b72= Te6edf3y Tff7b72+ Te6edf3_offset
Te6edf3y_prev Tff7b72= Tb4b4b4{Ta5d6ff"Ta5d6fftTa5d6ff"Tb4b4b4: Te6edf3yoff Tff7b72- Te6edf3heightTb4b4b4, Ta5d6ff"Ta5d6ffbTa5d6ff"Tb4b4b4: Te6edf3yoff Tff7b72+ Te6edf3heightTb4b4b4}
Te6edf3y_next Tff7b72= Tb4b4b4{Ta5d6ff"Ta5d6fftTa5d6ff"Tb4b4b4: Te6edf3yoff Tff7b72+ Te6edf3heightTb4b4b4, Ta5d6ff"Ta5d6ffbTa5d6ff"Tb4b4b4: Te6edf3yoff Tff7b72- Te6edf3heightTb4b4b4}
Tff7b72if Te6edf3_prevTb4b4b4:
Te6edf3_prevTff7b72.Td2a8ffpos Tff7b72= Tb4b4b4(Te6edf3xTb4b4b4, Te6edf3y_prevTb4b4b4[Te6edf3directionTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4]Tb4b4b4)
Tff7b72elif Te6edf3_loop Tff7b72and Te6edf3_next Tff7b72and Te6edf3index Tff7b72== T79c0ff0Tb4b4b4:
Tff7b72if Tb4b4b4(Te6edf3_offset Tff7b72> T79c0ff0 Tff7b72and Te6edf3directionTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6fftTa5d6ff"Tb4b4b4) Tff7b72or Tb4b4b4(
Te6edf3_offset Tff7b72< T79c0ff0 Tff7b72and Te6edf3directionTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6ffbTa5d6ff"
Tb4b4b4)Tb4b4b4:
Te6edf3last_slideTff7b72.Td2a8ffpos Tff7b72= Tb4b4b4(Te6edf3xTb4b4b4, Te6edf3y_prevTb4b4b4[Te6edf3directionTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4]Tb4b4b4)
Te6edf3skip_next Tff7b72= Tff7b72True
Tff7b72if Te6edf3_currentTb4b4b4:
Te6edf3_currentTff7b72.Td2a8ffpos Tff7b72= Tb4b4b4(Te6edf3xTb4b4b4, Te6edf3yoffTb4b4b4)
Tff7b72if Te6edf3skip_nextTb4b4b4:
Tff7b72return
Tff7b72if Te6edf3_nextTb4b4b4:
Te6edf3_nextTff7b72.Td2a8ffpos Tff7b72= Tb4b4b4(Te6edf3xTb4b4b4, Te6edf3y_nextTb4b4b4[Te6edf3directionTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4]Tb4b4b4)
Tff7b72elif Te6edf3_loop Tff7b72and Te6edf3_prev Tff7b72and Te6edf3index Tff7b72== Te6edf3no_of_slidesTb4b4b4:
Tff7b72if Tb4b4b4(Te6edf3_offset Tff7b72< T79c0ff0 Tff7b72and Te6edf3directionTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6fftTa5d6ff"Tb4b4b4) Tff7b72or Tb4b4b4(
Te6edf3_offset Tff7b72> T79c0ff0 Tff7b72and Te6edf3directionTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6ffbTa5d6ff"
Tb4b4b4)Tb4b4b4:
Te6edf3first_slideTff7b72.Td2a8ffpos Tff7b72= Tb4b4b4(Te6edf3xTb4b4b4, Te6edf3y_nextTb4b4b4[Te6edf3directionTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4]Tb4b4b4)
Tff7b72def Td2a8ffon_touch_downTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3touchTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_scrolling Tff7b72= Tff7b72True
Tff7b72return Tffa657superTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffon_touch_downTb4b4b4(Te6edf3touchTb4b4b4)
Tff7b72def Td2a8ffon_touch_upTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3touchTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_scrolling Tff7b72= Tff7b72False
Tff7b72return Tffa657superTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffon_touch_upTb4b4b4(Te6edf3touchTb4b4b4)
Tff7b72def Td2a8ff_start_animationTb4b4b4(Tff7b72selfTb4b4b4, Tff7b72*Te6edf3argsTb4b4b4, Tff7b72*Tff7b72*Te6edf3kwargsTb4b4b4)Tb4b4b4:
T8b949e# compute target offset for ease back, next or prev
Te6edf3new_offset Tff7b72= T79c0ff0
Te6edf3direction Tff7b72= Te6edf3kwargsTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffdirectionTa5d6ff"Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffdirectionTb4b4b4)Tb4b4b4[T79c0ff0Tb4b4b4]
Te6edf3is_horizontal Tff7b72= Te6edf3direction Tff7b72in Ta5d6ff"Ta5d6ffrlTa5d6ff"
Te6edf3extent Tff7b72= Tff7b72selfTff7b72.Td2a8ffwidth Tff7b72if Te6edf3is_horizontal Tff7b72else Tff7b72selfTff7b72.Td2a8ffheight
Te6edf3min_move Tff7b72= Te6edf3kwargsTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffmin_moveTa5d6ff"Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffmin_moveTb4b4b4)
Te6edf3_offset Tff7b72= Te6edf3kwargsTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffoffsetTa5d6ff"Tb4b4b4, Tff7b72selfTff7b72.Td2a8ff_offsetTb4b4b4)
Tff7b72if Te6edf3_offset Tff7b72< Te6edf3min_move Tff7b72* Tff7b72-Te6edf3extentTb4b4b4:
Te6edf3new_offset Tff7b72= Tff7b72-Te6edf3extent
Tff7b72elif Te6edf3_offset Tff7b72> Te6edf3min_move Tff7b72* Te6edf3extentTb4b4b4:
Te6edf3new_offset Tff7b72= Te6edf3extent
T8b949e# if new_offset is 0, it wasnt enough to go next/prev
Te6edf3dur Tff7b72= Tff7b72selfTff7b72.Td2a8ffanim_move_duration
Tff7b72if Te6edf3new_offset Tff7b72== T79c0ff0Tb4b4b4:
Te6edf3dur Tff7b72= Tff7b72selfTff7b72.Td2a8ffanim_cancel_duration
T8b949e# detect edge cases if not looping
Te6edf3len_slides Tff7b72= Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ffslidesTb4b4b4)
Te6edf3index Tff7b72= Tff7b72selfTff7b72.Td2a8ffindex
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffloop Tff7b72or Te6edf3len_slides Tff7b72== T79c0ff1Tb4b4b4:
Te6edf3is_first Tff7b72= Te6edf3index Tff7b72== T79c0ff0
Te6edf3is_last Tff7b72= Te6edf3index Tff7b72== Te6edf3len_slides Tff7b72- T79c0ff1
Tff7b72if Te6edf3direction Tff7b72in Ta5d6ff"Ta5d6ffrtTa5d6ff"Tb4b4b4:
Te6edf3towards_prev Tff7b72= Te6edf3new_offset Tff7b72> T79c0ff0
Te6edf3towards_next Tff7b72= Te6edf3new_offset Tff7b72< T79c0ff0
Tff7b72elseTb4b4b4:
Te6edf3towards_prev Tff7b72= Te6edf3new_offset Tff7b72< T79c0ff0
Te6edf3towards_next Tff7b72= Te6edf3new_offset Tff7b72> T79c0ff0
Tff7b72if Tb4b4b4(Te6edf3is_first Tff7b72and Te6edf3towards_prevTb4b4b4) Tff7b72or Tb4b4b4(Te6edf3is_last Tff7b72and Te6edf3towards_nextTb4b4b4)Tb4b4b4:
Te6edf3new_offset Tff7b72= T79c0ff0
Te6edf3anim Tff7b72= Te6edf3AnimationTb4b4b4(Te6edf3_offsetTff7b72=Te6edf3new_offsetTb4b4b4, Te6edf3dTff7b72=Te6edf3durTb4b4b4, Te6edf3tTff7b72=Tff7b72selfTff7b72.Td2a8ffanim_typeTb4b4b4)
Te6edf3animTff7b72.Td2a8ffcancel_allTb4b4b4(Tff7b72selfTb4b4b4)
Tff7b72def Td2a8ff_cmpTb4b4b4(Tff7b72*Te6edf3argsTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffdispatchTb4b4b4(
Ta5d6ff"Ta5d6ffon_slide_completeTa5d6ff"Tb4b4b4,
Tff7b72selfTff7b72.Td2a8ffprevious_slideTb4b4b4,
Tff7b72selfTff7b72.Td2a8ffcurrent_slideTb4b4b4,
Tff7b72selfTff7b72.Td2a8ffnext_slideTb4b4b4,
Tb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_skip_slide Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffindex Tff7b72= Tff7b72selfTff7b72.Td2a8ff_skip_slide
Tff7b72selfTff7b72.Td2a8ff_skip_slide Tff7b72= Tff7b72None
Te6edf3animTff7b72.Td2a8ffbindTb4b4b4(
Te6edf3on_completeTff7b72=Te6edf3_cmpTb4b4b4,
Te6edf3on_progressTff7b72=Tff7b72lambda Tff7b72*Te6edf3argsTb4b4b4: Tff7b72selfTff7b72.Td2a8ffdispatchTb4b4b4(
Ta5d6ff"Ta5d6ffon_slide_progressTa5d6ff"Tb4b4b4, Tff7b72selfTff7b72.Td2a8ff_offset
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3animTff7b72.Td2a8ffstartTb4b4b4(Tff7b72selfTb4b4b4)
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────